package com.quanyan.comment.utils;


import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.util.StringUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.List;

/**
 * Created by zijun.song on 2015/6/26.
 */
public class ObjectUtil {

    /**
     * 将对象转换为xml
     * @param object
     * @return
     */
    public static String objectToXMLString(Object object) {
        Map<String, Object> map = objectToMap(object);
        return mapToXMLString(map);
    }

    /**
     * 将Map转换为xml
     * @param map
     * @return
     */
    public static String mapToXMLString(Map<String, Object> map) {
        StringBuffer buffer = new StringBuffer("<xml>");
        Object[] keys = map.keySet().toArray();
        Arrays.sort(keys);
        for (int i = 0; i < keys.length; i++) {
            String key = keys[i].toString();
            Object value = map.get(key);
            if (!StringUtils.isEmpty(value.toString())) {
                buffer.append("<" + key + ">" + value + "</" + key + ">");
            }
        }
        buffer.append("</xml>");
        return buffer.toString();
    }




    /**
     * 将对象转换为map
     * @param object
     * @return
     */
    public static Map<String, Object> objectToMap(Object object) {
        if (object == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            Object obj;
            try {
                field.setAccessible(true);
                obj = field.get(object);
                if (obj != null) {
                    map.put(field.getName(), obj.toString());
                }
                obj = field.get(object);
                if(!isJavaBasicObject(field.getType()) && !field.getType().isPrimitive() && obj != null){
                    obj = objectToMapString(field.get(object));
                    if (obj != null) {
                        map.put(field.getName(), objectToMapString(field.get(object)));
                    }else {
                        map.put(field.getName(), "");
                    }
                }else {
                    if (obj != null) {
                        map.put(field.getName(), obj.toString());
                    }else {
                        map.put(field.getName(), "");
                    }
                }
                field.setAccessible(false);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }
    /**
     * 将对象转换为map
     * @param object
     * @return
     */
    public static Map<String, String> objectToMapString(Object object) {
        if (object == null) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            Object obj;
            try {
                field.setAccessible(true);
                obj = field.get(object);
                if (obj != null) {
                    map.put(field.getName(), obj.toString());
                }
                field.setAccessible(false);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }

    /**
     * 将map转化为对象
     * @param map
     * @param beanClass
     * @return
     */
    public static Object mapToObject(Map<String, Object> map, Class<?> beanClass) throws IllegalAccessException, InstantiationException {
        if (map == null) {
            return null;
        }
        Object obj = beanClass.newInstance();

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            int mod = field.getModifiers();
            if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
                continue;
            }
            field.set(obj, map.get(field.getName()));
        }
        return obj;
    }

    /**
     * xml to map xml <node><key label="key1">value1</key><key
     * label="key2">value2</key>......</node>
     *
     * @param xml
     * @return
     */
    public static Map<String,String> convertXmlToMap(String xml) {
        if (xml == null){
            return null;
        }
        try {
            Map<String,String> map = new HashMap<String,String>();
            Document document = DocumentHelper.parseText(xml);
            Element nodeElement = document.getRootElement();
            List node = nodeElement.elements();
            for (Iterator it = node.iterator(); it.hasNext();) {
                Element elm = (Element) it.next();
                if (elm.attributeValue("label") == null){
                    map.put(elm.getQualifiedName(), elm.getText());
                }else {
                    map.put(elm.attributeValue("label"), elm.getText());
                }
                elm = null;
            }
            node = null;
            nodeElement = null;
            document = null;
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getFullStackTraceToString(Exception exception) {
        StringWriter stringWriter = new StringWriter();
        exception.printStackTrace(new PrintWriter(stringWriter, true));
        return stringWriter.toString();
    }

    private static boolean isJavaBasicObject(Object object) {
        return object == Integer.class || object == String.class ||
                object == Double.class || object == Float.class || object == Long.class
                || object == Boolean.class || object == Date.class;
    }



    public static void main(String[] args){
        String xml = "<xml>\n" +
                "   <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                "   <return_msg><![CDATA[OK]]></return_msg>\n" +
                "   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
                "   <mch_id><![CDATA[10000100]]></mch_id>\n" +
                "   <nonce_str><![CDATA[NfsMFbUFpdbEhPXP]]></nonce_str>\n" +
                "   <sign><![CDATA[B7274EB9F8925EB93100DD2085FA56C0]]></sign>\n" +
                "   <result_code><![CDATA[SUCCESS]]></result_code>\n" +
                "   <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
                "   <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
                "   <out_refund_no><![CDATA[1415701182]]></out_refund_no>\n" +
                "   <refund_id><![CDATA[2008450740201411110000174436]]></refund_id>\n" +
                "   <refund_channel><![CDATA[]]></refund_channel>\n" +
                "   <refund_fee>1</refund_fee>\n" +
                "   <coupon_refund_fee>0</coupon_refund_fee>\n" +
                "</xml>";

        Map<String,String> map = convertXmlToMap(xml);

        System.out.println(map.get("return_code"));
        System.out.println(map.get("appid"));
        System.out.println(map.get("mch_id"));
        System.out.println(map.get("sign"));
        System.out.println(map.get("transaction_id"));

    }
}
